package com.wxy.ej.flow.modules.taskflow.service.nodeExecuteStrategy.strategy.in;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.rt.easyjava.common.base.Result;
import com.rt.easyjava.common.config.SpringContextBaseHolder;
import com.rt.easyjava.common.utils.others.StringUtils;
import com.wxy.ej.flow.modules.taskflow.dto.DataDto;
import com.wxy.ej.flow.modules.taskflow.dto.NodeDto;
import com.wxy.ej.flow.modules.taskflow.repository.JdbcRepository;
import com.wxy.ej.flow.modules.taskflow.service.nodeExecuteStrategy.NodeStrategy;
import com.wxy.ej.flow.utils.RegexUtils;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

@Slf4j
public class InJdbcPageStrategy extends NodeStrategy {

    @Override
    public Result action(NodeDto node, JSONObject flowDataJson, DataDto dataDto)  throws Exception{
        log.info("InJdbcPageStrategy: ");

        Long dataSourceId = node.getDataSourceId();
        String sqlColumn = node.getSqlColumn();
        String sqlCount = node.getSqlCount();
        String sqlWhere = node.getSqlWhere();
        String sqlLimit = node.getSqlLimit();

        // 验证
        if (sqlColumn==null) {
            return Result.builder().fault("sql is null");
        }
        if (sqlCount==null) {
            return Result.builder().fault("sql is null");
        }

        JdbcRepository jdbcRepository = SpringContextBaseHolder.getBean("jdbcRepository");
        StringBuilder sqlFullSb = new StringBuilder();
        sqlFullSb.append(sqlColumn).append(" ");
        StringBuilder sqlCountSb = new StringBuilder();
        sqlCountSb.append(sqlCount).append(" ");
        // 正则从sql script中, 取${item.id}
        String pattern = "\\$\\{[\\w.}\\[\\]]*";

        // condition
        StringBuilder conditionSqlSb = new StringBuilder();
        List<Object> sqlParamList = new ArrayList<>();
        if(!StringUtils.isNull(sqlWhere)) {
            sqlWhere = sqlWhere.replaceAll("\n","");
            // eg: ["name=${param.name}","email=${param.email}"]
            List<String> conditionList = Arrays.asList(sqlWhere.split(";"));
            //
            for(String condition: conditionList) {
                // 正则从sql script中, 取${item.id}
                List<String> jsScriptList = RegexUtils.searchMatch(condition, pattern,0);
                // 条件直接用常量，如：name='zhang3'
                if (jsScriptList.size()==0){
                    conditionSqlSb.append(condition).append(" and ");
                    continue;
                }
                String jsScript = jsScriptList.get(0);
                // 执行js取值
                String jsScript2 = jsScript.substring(2, jsScript.length()-1);
                Object o = executeScriptForResult(dataDto, jsScript2);
                if (StringUtils.isNull(o)) {
                    continue;
                }
                String conditionExp = condition.replace(jsScript, "?");
                conditionSqlSb.append(conditionExp).append(" and ");
                if (condition.contains(" like ")) {
                    sqlParamList.add("%"+o+"%");
                }else {
                    sqlParamList.add(o);
                }
            }
            if (conditionSqlSb.length()>0) {
                conditionSqlSb.delete(conditionSqlSb.length()-4, conditionSqlSb.length());
                sqlFullSb.append("where ").append(conditionSqlSb.toString());
                sqlCountSb.append("where ").append(conditionSqlSb.toString());
            }
        }

        // select count
        // log
        String sqlCountFull = sqlCountSb.toString();
        dataDto.getLogList().add(sqlCountFull);
        dataDto.getLogList().add(JSONArray.toJSONString(sqlParamList));
        // exec sql
        List<Map<String, Object>> totalList = jdbcRepository.executeQuery(sqlCountFull, sqlParamList);
        Map<String, Object> totalMap = totalList.get(0);
        String key = (String)totalMap.keySet().toArray()[0];
        Object total = totalMap.get(key);
        // save data
        String inDataToStorageMapVar4PageTotal = node.getDefineVarName4PageTotal();
        dataDto.getStorageDataVarMap().put(inDataToStorageMapVar4PageTotal, total);
        dataDto.getLogList().add("保存数据在"+inDataToStorageMapVar4PageTotal+"里，总记录数："+total);

        // limit
        // 正则从sql script中, 取${item.id}
        List<String> jsScriptList = RegexUtils.searchMatch(sqlLimit, pattern,0);
        // 执行js取值
        for (String jsScript:jsScriptList) {
            String jsScript2 = jsScript.substring(2, jsScript.length()-1);
            Object o = executeScriptForResult(dataDto, jsScript2);
            sqlLimit = sqlLimit.replace(jsScript, "?");
            sqlParamList.add(o);
        }
        sqlFullSb.append(sqlLimit);

        // log
        String sqlFull = sqlFullSb.toString();
        dataDto.getLogList().add(sqlFull);
        dataDto.getLogList().add(JSONArray.toJSONString(sqlParamList));

        // 取当前数据源执行sql
        List<Map<String, Object>> list = jdbcRepository.executeQuery(sqlFull, sqlParamList);

        // 保存数据
        String inDataToStorageMapVar = node.getDefineVarName();
        dataDto.getStorageDataVarMap().put(inDataToStorageMapVar, list);
        dataDto.getLogList().add("保存数据在"+inDataToStorageMapVar+"里，记录数："+list.size());

        return Result.builder(list);
    }
}
